﻿using System;
using System.Collections;
using System.Collections.Generic;

using Microsoft.Xna.Framework.Input;

namespace xEngine.Input
{
    class KeyDefinitionCollection : IEnumerable
    {
        #region Member Variables

        private List<KeyDefinition> _definitions;

        #endregion

        #region Properties

        public KeyDefinition this[Keys key]
        {
            get
            {
                foreach (KeyDefinition kd in _definitions)
                    if (kd.Key.Equals(key))
                        return kd;

                return null;
            }
        }
        public int Size
        {
            get { return _definitions.Count; }
        }

        #endregion

        #region Constructors

        public KeyDefinitionCollection()
        {
            _definitions = new List<KeyDefinition>(256);
        }

        #endregion

        #region Functions

        // Adds new definition for specified key
        public void AddDefinition(string key, EventHandler<KeyDefinitionEventArgs> keyEvent, KeyModifier modifier)
        {
            if (key == null || key == string.Empty || keyEvent == null)
                return;

            Keys k;
            if(Enum.TryParse<Keys>(key, true, out k))
                AddDefinition(k, keyEvent, modifier);
        }
        public void AddDefinition(Keys key, EventHandler<KeyDefinitionEventArgs> keyEvent, KeyModifier modifier)
        {
            if (keyEvent != null)
            {
                KeyDefinition def = this[key];

                // Key definition exists
                if(def != null && def.Modifier == modifier)
                    def.EventHandler += keyEvent;
                else
                    AddDefinition(new KeyDefinition(key, keyEvent, modifier));
            }
        }
        private void AddDefinition(KeyDefinition definition)
        {
            if(definition != null)
                _definitions.Add(definition);
        }
        // Clears definition linked to provided key
        public void RemoveDefinition(string key)
        {
            if (key == null || key == string.Empty)
                return;

            Keys k;
            if (Enum.TryParse<Keys>(key, true, out k))
                RemoveDefinition(k);
        }
        public void RemoveDefinition(Keys key)
        {
            RemoveDefinition(this[key]);
        }
        private void RemoveDefinition(KeyDefinition definition)
        {
            if(definition != null)
                _definitions.Remove(definition);
        }

        #endregion

        #region Operators

        public static KeyDefinitionCollection operator +(KeyDefinitionCollection collection, KeyDefinition definition)
        {
            collection.AddDefinition(definition);
            return collection;
        }

        #endregion

        #region IEnumerable

        public KDEnumerator GetEnumerator()
        {
            return new KDEnumerator(this);
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public class KDEnumerator : IEnumerator
        {
            int nIndex;
            KeyDefinitionCollection collection;

            public KDEnumerator(KeyDefinitionCollection collection)
            {
                this.collection = collection;
                nIndex = -1;
            }

            public void Reset()
            {
                nIndex = -1;
            }

            public bool MoveNext()
            {
                nIndex++;
                return (nIndex < collection._definitions.Count);
            }

            public KeyDefinition Current
            {
                get { return collection._definitions[nIndex]; }
            }

            object IEnumerator.Current
            {
                get { return (Current); }
            }
        }

        #endregion
    }

    class KeyDefinition
    {
        #region Member Variables

        public readonly Keys Key;
        public EventHandler<KeyDefinitionEventArgs> EventHandler;
        public readonly KeyModifier Modifier;

        #endregion

        #region Constructors

        public KeyDefinition(Keys key, EventHandler<KeyDefinitionEventArgs> eventHandler, KeyModifier modifier)
        {
            Key = key;
            EventHandler = eventHandler;
            Modifier = modifier;
        }

        #endregion
    }
}
